﻿Imports Runa.Common.Helper
Imports MS.Internal.Threading
Imports Runa.UI.Threading.Dispatcher
Imports Runa.Foundation.Threading

Namespace Global.Runa.UI.Threading

    Public Delegate Function DispatcherOperationCallback(ByVal arg As Object) As Object

    Public Class ExceptionEventArgs
        Inherits EventArgs

        Public Property Exception() As Exception
        Public Property Handled() As Boolean

        Public Sub New()
            Me.Exception = Nothing
            Me.Handled = False
        End Sub

        Public Sub New(ByVal e As Exception)
            Me.Exception = e
            Me.Handled = False
        End Sub

    End Class

    Friend Class ExceptionWrapper
        Public Event [Catch] As CatchHandler
        Public Event Filter As FilterHandler

        Public Delegate Sub CatchHandler(ByVal source As Object, ByVal e As ExceptionEventArgs)
        Public Delegate Sub FilterHandler(ByVal source As Object, ByVal e As ExceptionEventArgs)

        Private _exceptionFilterHelper As ExceptionFilterHelper

        Friend Sub New()
            Me._exceptionFilterHelper = New ExceptionFilterHelper(New InternalRealCallDelegate(AddressOf Me.InternalRealCall), New FilterExceptionDelegate(AddressOf Me.FilterException), New CatchExceptionDelegate(AddressOf Me.CatchException))
        End Sub

        Private Function CatchException(ByVal source As Object, ByVal e As Exception, ByVal catchHandler As [Delegate]) As Boolean
            If (Not catchHandler Is Nothing) Then
                If TypeOf catchHandler Is DispatcherOperationCallback Then
                    DirectCast(catchHandler, DispatcherOperationCallback)(Nothing)
                Else
                    catchHandler.DynamicInvoke(Nothing)
                End If
            End If
#If NETFX_CORE Or WINDOWS_PHONE Then
            Dim arg = New ExceptionEventArgs(e)
            RaiseEvent Catch(source, arg)
            Return arg.Handled
#Else
            Dim result = HasHandler(Me, "Catch")
            If result Then
                Dim arg = New ExceptionEventArgs(e)
                RaiseEvent Catch(source, arg)
                result = result AndAlso arg.Handled
            End If
            Return result
#End If
        End Function

        Private Function FilterException(ByVal source As Object, ByVal e As Exception) As Boolean
#If NETFX_CORE Or WINDOWS_PHONE Then
            RaiseEvent Filter(source, New ExceptionEventArgs(e))
            Return True
#Else
            Dim flag As Boolean = HasHandler(Me, "Catch")
            If HasHandler(Me, "Filter") Then
                RaiseEvent Filter(source, New ExceptionEventArgs(e))
            End If
            Return flag
#End If
        End Function

        Private Function InternalRealCall(ByVal callback As [Delegate], ByVal args As Object, ByVal numArgs As Integer) As Object
            Dim obj2 As Object = Nothing
            Dim num As Integer = numArgs
            Dim arg As Object = args
            If (numArgs = -1) Then
                Dim objArray As Object() = DirectCast(args, Object())
                If ((objArray Is Nothing) OrElse (objArray.Length = 0)) Then
                    num = 0
                ElseIf (objArray.Length = 1) Then
                    num = 1
                    arg = objArray(0)
                End If
            End If
            If (num = 0) Then
                Dim action As Action = TryCast(callback, Action)
                If (Not action Is Nothing) Then
                    action.Invoke()
                    Return obj2
                End If
                Dim callback4 As ShutdownCallback = TryCast(callback, ShutdownCallback)
                If (Not callback4 Is Nothing) Then
                    callback4.Invoke()
                    Return obj2
                End If
                Return callback.DynamicInvoke(New Object(0 - 1) {})
            End If
            If (num = 1) Then
                Dim callback3 As DispatcherOperationCallback = TryCast(callback, DispatcherOperationCallback)
                If (Not callback3 Is Nothing) Then
                    Return callback3(arg)
                End If
                Dim callback2 As SendOrPostCallback = TryCast(callback, SendOrPostCallback)
                If (Not callback2 Is Nothing) Then
                    callback2.Invoke(arg)
                    Return obj2
                End If
                If (numArgs = -1) Then
                    Return callback.DynamicInvoke(DirectCast(args, Object()))
                End If
                Return callback.DynamicInvoke(New Object() {args})
            End If
            Return callback.DynamicInvoke(DirectCast(args, Object()))
        End Function

        Public Function TryCatchWhen(ByVal source As Object, ByVal callback As [Delegate], ByVal args As Object, ByVal numArgs As Integer, ByVal catchHandler As [Delegate]) As Object
            Return Me._exceptionFilterHelper.TryCatchWhen(source, callback, args, numArgs, catchHandler)
        End Function

    End Class

End Namespace